﻿Imports System.Web
Imports WindowsLive

Namespace DNNCorp.Web
    Public Class RefreshMessengerTokenHandler
        Inherits BaseHttpHandler

        '
        ' * Configuration:
        ' * The minium requirement is to specify the application id and application secret in web.config
        ' * Refer to the boolean constructor of the WindowsLiveLogin for additional configuration options.
        ' * 
        ' * Configuration example:
        ' * <appSettings>
        ' * ...
        ' * <add key="wll_appid" value="my-application-id" />
        ' * <add key="wll_secret" value="my-application-secret" />
        ' * ...
        ' * </appSettings>
        ' 


        ''' <summary>
        ''' The name of the consent token cookie
        ''' </summary>
        Private Const ConsentTokenCookieName As String = "msgr-consent-token"

        ''' <summary>
        ''' The name of the delegation token cookie
        ''' </summary> 
        Private Const DelegationTokenCookieName As String = "msgr-delegation-token"

        ''' <summary>
        ''' Current consent token that is stored in the conset cookie
        ''' </summary>
        Private consentToken As String = Nothing

        ''' <summary>
        ''' Provides token processing functionality
        ''' </summary>
        Private m_windowsLiveLogin As WindowsLiveLogin

        ''' <summary>
        ''' Tests whether the consent token cookie is available
        ''' </summary>
        ''' <returns>'true' if the consent token cookie is available</returns>
        Private Function IsConsentCookieAvailable() As Boolean
            Dim consentTokenCookie As HttpCookie = Request.Cookies(ConsentTokenCookieName)

            If consentTokenCookie Is Nothing Then
                Return False
            End If

            Me.consentToken = consentTokenCookie.Value

            Return Not String.IsNullOrEmpty(Me.consentToken)
        End Function

        ''' <summary>
        ''' Refreshes the token
        ''' </summary>
        Private Sub RefreshDelegatedAuthenticationCookie()
            m_windowsLiveLogin = New WindowsLiveLogin(True)

            Dim token As WindowsLiveLogin.ConsentToken = m_windowsLiveLogin.ProcessConsentToken(Me.consentToken)
            Dim expireDelegationToken As Boolean = False

            If token Is Nothing Then
                expireDelegationToken = True
            Else
                If Not token.IsValid() Then
                    If token.Refresh() Then
                        UpdateDelegatedAuthenticationCookie(token)
                    Else
                        expireDelegationToken = True
                    End If
                ElseIf Not IsDelegationTokenCookiePresent() Then
                    UpdateDelegatedAuthenticationCookie(token)
                End If
            End If

            If expireDelegationToken Then
                ExpireDelegatedAuthenticatonCookie()
            End If
        End Sub

        ''' <summary>
        ''' Updates the cookies with a refreshed token
        ''' </summary>
        ''' <param name="token">The refreshed token</param>
        Private Sub UpdateDelegatedAuthenticationCookie(ByVal token As WindowsLiveLogin.ConsentToken)
            Dim delAuthCookie As New HttpCookie(DelegationTokenCookieName)
            delAuthCookie.Value = token.DelegationToken
            delAuthCookie.Path = "/"
            Response.Cookies.Add(delAuthCookie)

            Dim consentCookie As New HttpCookie(ConsentTokenCookieName)
            consentCookie.Value = token.Token
            consentCookie.Path = "/"
            Response.Cookies.Add(consentCookie)
        End Sub

        ''' <summary>
        ''' Expires the delegation token cookie
        ''' </summary>
        Private Sub ExpireDelegatedAuthenticatonCookie()
            ExpireCookie(DelegationTokenCookieName)
        End Sub

        ''' <summary>
        ''' Expires a given cookie
        ''' </summary>
        ''' <param name="cookieName">The name of the cookie to expire</param>
        Private Sub ExpireCookie(ByVal cookieName As String)
            Dim cookie As New HttpCookie(DelegationTokenCookieName)
            cookie.Expires = DateTime.Now.AddYears(-1)
            cookie.Path = "/"
            Response.Cookies.Add(cookie)
        End Sub

        ''' <summary>
        ''' Checks if the delegation token cookie is present
        ''' </summary>
        ''' <returns>'true' is returned if the delegation cookie is present</returns>
        Private Function IsDelegationTokenCookiePresent() As Boolean
            Dim cookie As HttpCookie = Request.Cookies(DelegationTokenCookieName)
            Return cookie IsNot Nothing AndAlso Not String.IsNullOrEmpty(cookie.Value)
        End Function

        Private Sub HandleException(ByVal e As Exception)
            ' The application should log the exception as it may be caused due to a configuration issue
        End Sub

        Public Overrides Sub HandleRequest()
            Try
                If IsConsentCookieAvailable() Then
                    RefreshDelegatedAuthenticationCookie()
                End If
            Catch ex As Exception
                HandleException(ex)
            End Try

            Response.Write(<html xmlns="http://www.w3.org/1999/xhtml">
                               <head>
                                   <title></title>
                               </head>
                               <body>
                                   <div></div>
                               </body>
                           </html>)
        End Sub

        Public Overrides Function ValidateParameters() As Boolean
            Return True
        End Function

        Public Overrides ReadOnly Property ContentMimeType() As String
            Get
                Return "text/html"
            End Get
        End Property

        Public Overrides ReadOnly Property RequiresAuthentication() As Boolean
            Get
                Return False
            End Get
        End Property
    End Class

End Namespace